﻿// Accord Math Library
// The Accord.NET Framework
// http://accord-framework.net
//
// Copyright © César Souza, 2009-2017
// cesarsouza at gmail.com
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Lesser General Public
//    License as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public
//    License along with this library; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//

// ======================================================================
// This code has been generated by a tool; do not edit manually. Instead,
// edit the T4 template Vector.Random.tt so this file can be regenerated. 
// ======================================================================


namespace Accord.Math
{
    using System;
    using Accord.Math;

    public static partial class Vector
    {


        /// <summary>
        ///   Returns a vector containing indices (0, 1, 2, ..., n - 1) in random 
        ///   order. The vector grows up to to <paramref name="size"/>, but does not
        ///   include <c>size</c> among its values.
        /// </summary>
        ///
        /// <param name="size">The size of the sample vector to be generated.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3);  // a possible output is { 2, 1, 0 };
        ///   var b = Vector.Sample(10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static int[] Sample(int size)
        {
            var random = Accord.Math.Random.Generator.Random;

            var idx = Vector.Range(size);
            var x = new double[idx.Length];
            for (int i = 0; i < x.Length; i++)
                x[i] = random.NextDouble();

            Array.Sort(x, idx);

            return idx;
        }
        
        /// <summary>
        ///   Returns a vector of the specified <paramref name="sampleSize"/> containing 
        ///   non-repeating indices in the range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="sampleSize">The size of the sample vector to be generated.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <remarks>
        ///   In other words, this return a sample of size <c>k</c> from a population
        ///   of size <c>N</c>, where <c>k</c> is the parameter <paramref name="sampleSize"/>
        ///   and <c>N</c> is the parameter <paramref name="populationSize"/>.
        /// </remarks>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(10, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static int[] Sample(int sampleSize, int populationSize)
        {
            if ((int)sampleSize > populationSize)
            {
                throw new ArgumentOutOfRangeException("size", String.Format(
                    "The sample size {0} must be less than the size of the population {1}.", 
                    sampleSize, populationSize));
            }

            int[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector of the specified <paramref name="percentage"/> of the 
        ///   <paramref name="populationSize"/> containing non-repeating indices in the 
        ///   range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="percentage">The percentage of the population to sample.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(0.3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(1.0, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(0.2, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static int[] Sample(double percentage, int populationSize)
        {
            if (percentage < 0 || percentage > 1)
            {
                throw new ArgumentOutOfRangeException("percentage", String.Format(
                    "The sample percentage {0} must be between 0 and 1.", percentage));
            }

            int sampleSize = (int)System.Math.Floor(percentage * (double)populationSize);

            int[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector containing indices (0, 1, 2, ..., n - 1) in random 
        ///   order. The vector grows up to to <paramref name="size"/>, but does not
        ///   include <c>size</c> among its values.
        /// </summary>
        ///
        /// <param name="size">The size of the sample vector to be generated.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3);  // a possible output is { 2, 1, 0 };
        ///   var b = Vector.Sample(10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static float[] Sample(float size)
        {
            var random = Accord.Math.Random.Generator.Random;

            var idx = Vector.Range(size);
            var x = new double[idx.Length];
            for (int i = 0; i < x.Length; i++)
                x[i] = random.NextDouble();

            Array.Sort(x, idx);

            return idx;
        }
        
        /// <summary>
        ///   Returns a vector of the specified <paramref name="sampleSize"/> containing 
        ///   non-repeating indices in the range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="sampleSize">The size of the sample vector to be generated.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <remarks>
        ///   In other words, this return a sample of size <c>k</c> from a population
        ///   of size <c>N</c>, where <c>k</c> is the parameter <paramref name="sampleSize"/>
        ///   and <c>N</c> is the parameter <paramref name="populationSize"/>.
        /// </remarks>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(10, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static float[] Sample(int sampleSize, float populationSize)
        {
            if ((float)sampleSize > populationSize)
            {
                throw new ArgumentOutOfRangeException("size", String.Format(
                    "The sample size {0} must be less than the size of the population {1}.", 
                    sampleSize, populationSize));
            }

            float[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector of the specified <paramref name="percentage"/> of the 
        ///   <paramref name="populationSize"/> containing non-repeating indices in the 
        ///   range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="percentage">The percentage of the population to sample.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(0.3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(1.0, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(0.2, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static float[] Sample(double percentage, float populationSize)
        {
            if (percentage < 0 || percentage > 1)
            {
                throw new ArgumentOutOfRangeException("percentage", String.Format(
                    "The sample percentage {0} must be between 0 and 1.", percentage));
            }

            int sampleSize = (int)System.Math.Floor(percentage * (double)populationSize);

            float[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector containing indices (0, 1, 2, ..., n - 1) in random 
        ///   order. The vector grows up to to <paramref name="size"/>, but does not
        ///   include <c>size</c> among its values.
        /// </summary>
        ///
        /// <param name="size">The size of the sample vector to be generated.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3);  // a possible output is { 2, 1, 0 };
        ///   var b = Vector.Sample(10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static double[] Sample(double size)
        {
            var random = Accord.Math.Random.Generator.Random;

            var idx = Vector.Range(size);
            var x = new double[idx.Length];
            for (int i = 0; i < x.Length; i++)
                x[i] = random.NextDouble();

            Array.Sort(x, idx);

            return idx;
        }
        
        /// <summary>
        ///   Returns a vector of the specified <paramref name="sampleSize"/> containing 
        ///   non-repeating indices in the range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="sampleSize">The size of the sample vector to be generated.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <remarks>
        ///   In other words, this return a sample of size <c>k</c> from a population
        ///   of size <c>N</c>, where <c>k</c> is the parameter <paramref name="sampleSize"/>
        ///   and <c>N</c> is the parameter <paramref name="populationSize"/>.
        /// </remarks>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(10, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static double[] Sample(int sampleSize, double populationSize)
        {
            if ((double)sampleSize > populationSize)
            {
                throw new ArgumentOutOfRangeException("size", String.Format(
                    "The sample size {0} must be less than the size of the population {1}.", 
                    sampleSize, populationSize));
            }

            double[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector of the specified <paramref name="percentage"/> of the 
        ///   <paramref name="populationSize"/> containing non-repeating indices in the 
        ///   range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="percentage">The percentage of the population to sample.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(0.3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(1.0, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(0.2, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static double[] Sample(double percentage, double populationSize)
        {
            if (percentage < 0 || percentage > 1)
            {
                throw new ArgumentOutOfRangeException("percentage", String.Format(
                    "The sample percentage {0} must be between 0 and 1.", percentage));
            }

            int sampleSize = (int)System.Math.Floor(percentage * (double)populationSize);

            double[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector containing indices (0, 1, 2, ..., n - 1) in random 
        ///   order. The vector grows up to to <paramref name="size"/>, but does not
        ///   include <c>size</c> among its values.
        /// </summary>
        ///
        /// <param name="size">The size of the sample vector to be generated.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3);  // a possible output is { 2, 1, 0 };
        ///   var b = Vector.Sample(10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static short[] Sample(short size)
        {
            var random = Accord.Math.Random.Generator.Random;

            var idx = Vector.Range(size);
            var x = new double[idx.Length];
            for (int i = 0; i < x.Length; i++)
                x[i] = random.NextDouble();

            Array.Sort(x, idx);

            return idx;
        }
        
        /// <summary>
        ///   Returns a vector of the specified <paramref name="sampleSize"/> containing 
        ///   non-repeating indices in the range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="sampleSize">The size of the sample vector to be generated.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <remarks>
        ///   In other words, this return a sample of size <c>k</c> from a population
        ///   of size <c>N</c>, where <c>k</c> is the parameter <paramref name="sampleSize"/>
        ///   and <c>N</c> is the parameter <paramref name="populationSize"/>.
        /// </remarks>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(10, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static short[] Sample(int sampleSize, short populationSize)
        {
            if ((short)sampleSize > populationSize)
            {
                throw new ArgumentOutOfRangeException("size", String.Format(
                    "The sample size {0} must be less than the size of the population {1}.", 
                    sampleSize, populationSize));
            }

            short[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector of the specified <paramref name="percentage"/> of the 
        ///   <paramref name="populationSize"/> containing non-repeating indices in the 
        ///   range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="percentage">The percentage of the population to sample.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(0.3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(1.0, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(0.2, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static short[] Sample(double percentage, short populationSize)
        {
            if (percentage < 0 || percentage > 1)
            {
                throw new ArgumentOutOfRangeException("percentage", String.Format(
                    "The sample percentage {0} must be between 0 and 1.", percentage));
            }

            int sampleSize = (int)System.Math.Floor(percentage * (double)populationSize);

            short[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector containing indices (0, 1, 2, ..., n - 1) in random 
        ///   order. The vector grows up to to <paramref name="size"/>, but does not
        ///   include <c>size</c> among its values.
        /// </summary>
        ///
        /// <param name="size">The size of the sample vector to be generated.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3);  // a possible output is { 2, 1, 0 };
        ///   var b = Vector.Sample(10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static byte[] Sample(byte size)
        {
            var random = Accord.Math.Random.Generator.Random;

            var idx = Vector.Range(size);
            var x = new double[idx.Length];
            for (int i = 0; i < x.Length; i++)
                x[i] = random.NextDouble();

            Array.Sort(x, idx);

            return idx;
        }
        
        /// <summary>
        ///   Returns a vector of the specified <paramref name="sampleSize"/> containing 
        ///   non-repeating indices in the range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="sampleSize">The size of the sample vector to be generated.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <remarks>
        ///   In other words, this return a sample of size <c>k</c> from a population
        ///   of size <c>N</c>, where <c>k</c> is the parameter <paramref name="sampleSize"/>
        ///   and <c>N</c> is the parameter <paramref name="populationSize"/>.
        /// </remarks>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(10, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static byte[] Sample(int sampleSize, byte populationSize)
        {
            if ((byte)sampleSize > populationSize)
            {
                throw new ArgumentOutOfRangeException("size", String.Format(
                    "The sample size {0} must be less than the size of the population {1}.", 
                    sampleSize, populationSize));
            }

            byte[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector of the specified <paramref name="percentage"/> of the 
        ///   <paramref name="populationSize"/> containing non-repeating indices in the 
        ///   range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="percentage">The percentage of the population to sample.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(0.3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(1.0, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(0.2, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static byte[] Sample(double percentage, byte populationSize)
        {
            if (percentage < 0 || percentage > 1)
            {
                throw new ArgumentOutOfRangeException("percentage", String.Format(
                    "The sample percentage {0} must be between 0 and 1.", percentage));
            }

            int sampleSize = (int)System.Math.Floor(percentage * (double)populationSize);

            byte[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector containing indices (0, 1, 2, ..., n - 1) in random 
        ///   order. The vector grows up to to <paramref name="size"/>, but does not
        ///   include <c>size</c> among its values.
        /// </summary>
        ///
        /// <param name="size">The size of the sample vector to be generated.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3);  // a possible output is { 2, 1, 0 };
        ///   var b = Vector.Sample(10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static sbyte[] Sample(sbyte size)
        {
            var random = Accord.Math.Random.Generator.Random;

            var idx = Vector.Range(size);
            var x = new double[idx.Length];
            for (int i = 0; i < x.Length; i++)
                x[i] = random.NextDouble();

            Array.Sort(x, idx);

            return idx;
        }
        
        /// <summary>
        ///   Returns a vector of the specified <paramref name="sampleSize"/> containing 
        ///   non-repeating indices in the range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="sampleSize">The size of the sample vector to be generated.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <remarks>
        ///   In other words, this return a sample of size <c>k</c> from a population
        ///   of size <c>N</c>, where <c>k</c> is the parameter <paramref name="sampleSize"/>
        ///   and <c>N</c> is the parameter <paramref name="populationSize"/>.
        /// </remarks>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(10, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static sbyte[] Sample(int sampleSize, sbyte populationSize)
        {
            if ((sbyte)sampleSize > populationSize)
            {
                throw new ArgumentOutOfRangeException("size", String.Format(
                    "The sample size {0} must be less than the size of the population {1}.", 
                    sampleSize, populationSize));
            }

            sbyte[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector of the specified <paramref name="percentage"/> of the 
        ///   <paramref name="populationSize"/> containing non-repeating indices in the 
        ///   range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="percentage">The percentage of the population to sample.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(0.3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(1.0, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(0.2, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static sbyte[] Sample(double percentage, sbyte populationSize)
        {
            if (percentage < 0 || percentage > 1)
            {
                throw new ArgumentOutOfRangeException("percentage", String.Format(
                    "The sample percentage {0} must be between 0 and 1.", percentage));
            }

            int sampleSize = (int)System.Math.Floor(percentage * (double)populationSize);

            sbyte[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector containing indices (0, 1, 2, ..., n - 1) in random 
        ///   order. The vector grows up to to <paramref name="size"/>, but does not
        ///   include <c>size</c> among its values.
        /// </summary>
        ///
        /// <param name="size">The size of the sample vector to be generated.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3);  // a possible output is { 2, 1, 0 };
        ///   var b = Vector.Sample(10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static long[] Sample(long size)
        {
            var random = Accord.Math.Random.Generator.Random;

            var idx = Vector.Range(size);
            var x = new double[idx.Length];
            for (int i = 0; i < x.Length; i++)
                x[i] = random.NextDouble();

            Array.Sort(x, idx);

            return idx;
        }
        
        /// <summary>
        ///   Returns a vector of the specified <paramref name="sampleSize"/> containing 
        ///   non-repeating indices in the range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="sampleSize">The size of the sample vector to be generated.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <remarks>
        ///   In other words, this return a sample of size <c>k</c> from a population
        ///   of size <c>N</c>, where <c>k</c> is the parameter <paramref name="sampleSize"/>
        ///   and <c>N</c> is the parameter <paramref name="populationSize"/>.
        /// </remarks>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(10, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static long[] Sample(int sampleSize, long populationSize)
        {
            if ((long)sampleSize > populationSize)
            {
                throw new ArgumentOutOfRangeException("size", String.Format(
                    "The sample size {0} must be less than the size of the population {1}.", 
                    sampleSize, populationSize));
            }

            long[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector of the specified <paramref name="percentage"/> of the 
        ///   <paramref name="populationSize"/> containing non-repeating indices in the 
        ///   range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="percentage">The percentage of the population to sample.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(0.3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(1.0, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(0.2, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static long[] Sample(double percentage, long populationSize)
        {
            if (percentage < 0 || percentage > 1)
            {
                throw new ArgumentOutOfRangeException("percentage", String.Format(
                    "The sample percentage {0} must be between 0 and 1.", percentage));
            }

            int sampleSize = (int)System.Math.Floor(percentage * (double)populationSize);

            long[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector containing indices (0, 1, 2, ..., n - 1) in random 
        ///   order. The vector grows up to to <paramref name="size"/>, but does not
        ///   include <c>size</c> among its values.
        /// </summary>
        ///
        /// <param name="size">The size of the sample vector to be generated.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3);  // a possible output is { 2, 1, 0 };
        ///   var b = Vector.Sample(10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static decimal[] Sample(decimal size)
        {
            var random = Accord.Math.Random.Generator.Random;

            var idx = Vector.Range(size);
            var x = new double[idx.Length];
            for (int i = 0; i < x.Length; i++)
                x[i] = random.NextDouble();

            Array.Sort(x, idx);

            return idx;
        }
        
        /// <summary>
        ///   Returns a vector of the specified <paramref name="sampleSize"/> containing 
        ///   non-repeating indices in the range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="sampleSize">The size of the sample vector to be generated.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <remarks>
        ///   In other words, this return a sample of size <c>k</c> from a population
        ///   of size <c>N</c>, where <c>k</c> is the parameter <paramref name="sampleSize"/>
        ///   and <c>N</c> is the parameter <paramref name="populationSize"/>.
        /// </remarks>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(10, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static decimal[] Sample(int sampleSize, decimal populationSize)
        {
            if ((decimal)sampleSize > populationSize)
            {
                throw new ArgumentOutOfRangeException("size", String.Format(
                    "The sample size {0} must be less than the size of the population {1}.", 
                    sampleSize, populationSize));
            }

            decimal[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector of the specified <paramref name="percentage"/> of the 
        ///   <paramref name="populationSize"/> containing non-repeating indices in the 
        ///   range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="percentage">The percentage of the population to sample.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(0.3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(1.0, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(0.2, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static decimal[] Sample(double percentage, decimal populationSize)
        {
            if (percentage < 0 || percentage > 1)
            {
                throw new ArgumentOutOfRangeException("percentage", String.Format(
                    "The sample percentage {0} must be between 0 and 1.", percentage));
            }

            int sampleSize = (int)System.Math.Floor(percentage * (double)populationSize);

            decimal[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector containing indices (0, 1, 2, ..., n - 1) in random 
        ///   order. The vector grows up to to <paramref name="size"/>, but does not
        ///   include <c>size</c> among its values.
        /// </summary>
        ///
        /// <param name="size">The size of the sample vector to be generated.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3);  // a possible output is { 2, 1, 0 };
        ///   var b = Vector.Sample(10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static ulong[] Sample(ulong size)
        {
            var random = Accord.Math.Random.Generator.Random;

            var idx = Vector.Range(size);
            var x = new double[idx.Length];
            for (int i = 0; i < x.Length; i++)
                x[i] = random.NextDouble();

            Array.Sort(x, idx);

            return idx;
        }
        
        /// <summary>
        ///   Returns a vector of the specified <paramref name="sampleSize"/> containing 
        ///   non-repeating indices in the range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="sampleSize">The size of the sample vector to be generated.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <remarks>
        ///   In other words, this return a sample of size <c>k</c> from a population
        ///   of size <c>N</c>, where <c>k</c> is the parameter <paramref name="sampleSize"/>
        ///   and <c>N</c> is the parameter <paramref name="populationSize"/>.
        /// </remarks>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(10, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static ulong[] Sample(int sampleSize, ulong populationSize)
        {
            if ((ulong)sampleSize > populationSize)
            {
                throw new ArgumentOutOfRangeException("size", String.Format(
                    "The sample size {0} must be less than the size of the population {1}.", 
                    sampleSize, populationSize));
            }

            ulong[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector of the specified <paramref name="percentage"/> of the 
        ///   <paramref name="populationSize"/> containing non-repeating indices in the 
        ///   range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="percentage">The percentage of the population to sample.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(0.3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(1.0, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(0.2, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static ulong[] Sample(double percentage, ulong populationSize)
        {
            if (percentage < 0 || percentage > 1)
            {
                throw new ArgumentOutOfRangeException("percentage", String.Format(
                    "The sample percentage {0} must be between 0 and 1.", percentage));
            }

            int sampleSize = (int)System.Math.Floor(percentage * (double)populationSize);

            ulong[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector containing indices (0, 1, 2, ..., n - 1) in random 
        ///   order. The vector grows up to to <paramref name="size"/>, but does not
        ///   include <c>size</c> among its values.
        /// </summary>
        ///
        /// <param name="size">The size of the sample vector to be generated.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3);  // a possible output is { 2, 1, 0 };
        ///   var b = Vector.Sample(10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static ushort[] Sample(ushort size)
        {
            var random = Accord.Math.Random.Generator.Random;

            var idx = Vector.Range(size);
            var x = new double[idx.Length];
            for (int i = 0; i < x.Length; i++)
                x[i] = random.NextDouble();

            Array.Sort(x, idx);

            return idx;
        }
        
        /// <summary>
        ///   Returns a vector of the specified <paramref name="sampleSize"/> containing 
        ///   non-repeating indices in the range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="sampleSize">The size of the sample vector to be generated.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <remarks>
        ///   In other words, this return a sample of size <c>k</c> from a population
        ///   of size <c>N</c>, where <c>k</c> is the parameter <paramref name="sampleSize"/>
        ///   and <c>N</c> is the parameter <paramref name="populationSize"/>.
        /// </remarks>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(10, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(5, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static ushort[] Sample(int sampleSize, ushort populationSize)
        {
            if ((ushort)sampleSize > populationSize)
            {
                throw new ArgumentOutOfRangeException("size", String.Format(
                    "The sample size {0} must be less than the size of the population {1}.", 
                    sampleSize, populationSize));
            }

            ushort[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }

        /// <summary>
        ///   Returns a vector of the specified <paramref name="percentage"/> of the 
        ///   <paramref name="populationSize"/> containing non-repeating indices in the 
        ///   range [0, populationSize) in random order.
        /// </summary>
        /// 
        /// <param name="percentage">The percentage of the population to sample.</param>
        /// <param name="populationSize">The non-inclusive maximum number an index can have.</param>
        /// 
        /// <example>
        /// <code>
        ///   var a = Vector.Sample(0.3, 10);  // a possible output is { 1, 7, 4 };
        ///   var b = Vector.Sample(1.0, 10); // a possible output is { 5, 4, 2, 0, 1, 3, 7, 9, 8, 6 };
        ///   
        ///   foreach (var i in Vector.Sample(0.2, 6))
        ///   {
        ///      // ...
        ///   }
        /// </code>
        /// </example>
        /// 
        public static ushort[] Sample(double percentage, ushort populationSize)
        {
            if (percentage < 0 || percentage > 1)
            {
                throw new ArgumentOutOfRangeException("percentage", String.Format(
                    "The sample percentage {0} must be between 0 and 1.", percentage));
            }

            int sampleSize = (int)System.Math.Floor(percentage * (double)populationSize);

            ushort[] idx = Sample(populationSize);
            return idx.First(sampleSize);
        }
        /// <summary>
        ///   Creates a vector with uniformly distributed random data.
        /// </summary>
        /// 
        public static int[] Random(int size, int min, int max)
        {
            if (size < 0)
                throw new ArgumentOutOfRangeException("size", size, "Size must be a positive integer.");

            var random = Accord.Math.Random.Generator.Random;

            var vector = new int[size];
            for (int i = 0; i < size; i++)
                vector[i] = (int)random.Next((int)min, (int)max);
            return vector;
        }
        /// <summary>
        ///   Creates a vector with uniformly distributed random data.
        /// </summary>
        /// 
        public static short[] Random(int size, short min, short max)
        {
            if (size < 0)
                throw new ArgumentOutOfRangeException("size", size, "Size must be a positive integer.");

            var random = Accord.Math.Random.Generator.Random;

            var vector = new short[size];
            for (int i = 0; i < size; i++)
                vector[i] = (short)random.Next((int)min, (int)max);
            return vector;
        }
        /// <summary>
        ///   Creates a vector with uniformly distributed random data.
        /// </summary>
        /// 
        public static byte[] Random(int size, byte min, byte max)
        {
            if (size < 0)
                throw new ArgumentOutOfRangeException("size", size, "Size must be a positive integer.");

            var random = Accord.Math.Random.Generator.Random;

            var vector = new byte[size];
            for (int i = 0; i < size; i++)
                vector[i] = (byte)random.Next((int)min, (int)max);
            return vector;
        }
        /// <summary>
        ///   Creates a vector with uniformly distributed random data.
        /// </summary>
        /// 
        public static sbyte[] Random(int size, sbyte min, sbyte max)
        {
            if (size < 0)
                throw new ArgumentOutOfRangeException("size", size, "Size must be a positive integer.");

            var random = Accord.Math.Random.Generator.Random;

            var vector = new sbyte[size];
            for (int i = 0; i < size; i++)
                vector[i] = (sbyte)random.Next((int)min, (int)max);
            return vector;
        }
        /// <summary>
        ///   Creates a vector with uniformly distributed random data.
        /// </summary>
        /// 
        public static long[] Random(int size, long min, long max)
        {
            if (size < 0)
                throw new ArgumentOutOfRangeException("size", size, "Size must be a positive integer.");

            var random = Accord.Math.Random.Generator.Random;

            var vector = new long[size];
            for (int i = 0; i < size; i++)
                vector[i] = (long)random.Next((int)min, (int)max);
            return vector;
        }
        /// <summary>
        ///   Creates a vector with uniformly distributed random data.
        /// </summary>
        /// 
        public static ulong[] Random(int size, ulong min, ulong max)
        {
            if (size < 0)
                throw new ArgumentOutOfRangeException("size", size, "Size must be a positive integer.");

            var random = Accord.Math.Random.Generator.Random;

            var vector = new ulong[size];
            for (int i = 0; i < size; i++)
                vector[i] = (ulong)random.Next((int)min, (int)max);
            return vector;
        }
        /// <summary>
        ///   Creates a vector with uniformly distributed random data.
        /// </summary>
        /// 
        public static ushort[] Random(int size, ushort min, ushort max)
        {
            if (size < 0)
                throw new ArgumentOutOfRangeException("size", size, "Size must be a positive integer.");

            var random = Accord.Math.Random.Generator.Random;

            var vector = new ushort[size];
            for (int i = 0; i < size; i++)
                vector[i] = (ushort)random.Next((int)min, (int)max);
            return vector;
        }
        /// <summary>
        ///   Creates a vector with uniformly distributed random data.
        /// </summary>
        /// 
        public static float[] Random(int size, float min, float max)
        {
            if (size < 0)
                throw new ArgumentOutOfRangeException("size", size, "Size must be a positive integer.");

            var random = Accord.Math.Random.Generator.Random;

            var vector = new float[size];
            for (int i = 0; i < size; i++)
                vector[i] = (float)random.NextDouble() * (max - min) + min;
            return vector;
        }
        /// <summary>
        ///   Creates a vector with uniformly distributed random data.
        /// </summary>
        /// 
        public static double[] Random(int size, double min, double max)
        {
            if (size < 0)
                throw new ArgumentOutOfRangeException("size", size, "Size must be a positive integer.");

            var random = Accord.Math.Random.Generator.Random;

            var vector = new double[size];
            for (int i = 0; i < size; i++)
                vector[i] = (double)random.NextDouble() * (max - min) + min;
            return vector;
        }
        /// <summary>
        ///   Creates a vector with uniformly distributed random data.
        /// </summary>
        /// 
        public static decimal[] Random(int size, decimal min, decimal max)
        {
            if (size < 0)
                throw new ArgumentOutOfRangeException("size", size, "Size must be a positive integer.");

            var random = Accord.Math.Random.Generator.Random;

            var vector = new decimal[size];
            for (int i = 0; i < size; i++)
                vector[i] = (decimal)random.NextDouble() * (max - min) + min;
            return vector;
        }
    }
}